/*
 * Copyright (C) 2015 tyrantgit
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tyrantgit.explosionfield;

import ohos.aafwk.ability.Ability;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Rect;
import ohos.app.Context;
import ohos.media.image.PixelMap;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

public class ExplosionField extends Component implements Component.DrawTask {
    private List<ExplosionAnimator> mExplosions;
    private int[] mExpandInset = new int[2];

    private Component component;

    private int offsetTop = 0;

    public ExplosionField(Context context, Component component) {
        super(context);
        this.component = component;
        mExplosions = new ArrayList<>();
        init();

    }


    public void refresh(){
        this.component.invalidate();
    }

    public ExplosionField(Context context, AttrSet attrs) {
        super(context, attrs);
        init();
    }

    public ExplosionField(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        Arrays.fill(mExpandInset, Utils.dp2Px(getContext(),32));
        component.addDrawTask(this);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {

        offsetTop = component.getLocationOnScreen()[1];

        for (ExplosionAnimator explosion : mExplosions) {
            explosion.draw(canvas, offsetTop);
        }
    }

    public void expandExplosionBound(int dx, int dy) {
        mExpandInset[0] = dx;
        mExpandInset[1] = dy;
    }

    public void explode(PixelMap bitmap, Rect bound, long startDelay, long duration) {

        final ExplosionAnimator explosion = new ExplosionAnimator(this, bitmap, bound);

        explosion.setStateChangedListener(new Animator.StateChangedListener() {

            @Override
            public void onStart(Animator animator) {
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
            }

            @Override
            public void onEnd(Animator animator) {
                mExplosions.remove(animator);
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });

        explosion.setDelay(startDelay);
        explosion.setDuration(duration);
        explosion.ofFloat(new float[]{0, 1.4F});
        mExplosions.add(explosion);
        explosion.start();
    }

        public void explode(final Component view) {

        Rect r = new Rect();
        int[] location = view.getLocationOnScreen();
        r.left = location[0];
        r.top = location[1];
        r.right = r.left + view.getWidth();
        r.bottom = r.top + view.getHeight();

        Utils.inset(r, -mExpandInset[0], -mExpandInset[1]);

        int startDelay = 150;

        AnimatorValue animator = new AnimatorValue();
        animator.setDuration(startDelay);
        animator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            Random random = new Random();
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                view.setTranslationX((random.nextFloat() - 0.5f) * view.getWidth() * 0.05f);
                view.setTranslationY((random.nextFloat() - 0.5f) * view.getHeight() * 0.05f);
            }
        });
        animator.start();

        view.createAnimatorProperty().setDuration(150).setDelay(startDelay).scaleX(0f).scaleY(0f).alpha(0f).start();

        explode(Utils.createBitmapFromView(view), r, startDelay, ExplosionAnimator.DEFAULT_DURATION);
    }

    public void clear() {
        mExplosions.clear();
        invalidate();
    }

    public static ExplosionField attach2Window(Ability ability, Component component) {

        ability.setUIContent(ResourceTable.Layout_layout);
        ComponentContainer componentContainer = (ComponentContainer)ability.findComponentById(ResourceTable.Id_explosion_field_root);
        ExplosionField explosionField = new ExplosionField(ability, component);
        componentContainer.addComponent(component);
        componentContainer.addComponent(explosionField, new ComponentContainer.LayoutConfig(
                ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT));

        return explosionField;
    }

}
